package biz.datalk.industrialland.admin.modules.system.util;

import org.apache.commons.lang3.StringUtils;

/**
 * 部门编码 生成规则
 * <p>
 * A01
 * A01A01
 * A01A02
 *
 * @author tarofang@163.com
 * @date 2020-05-27
 */
public class GenCodeUtil {
    /** 字母 */
    private static final String CODE_PREFIX = "A";
    /** 数字长度 */
    private static final int NUM_LEN = 2;

    private static final int ASCII_NUM_0 = 48;
    private static final int ASCII_NUM_9 = 57;
    private static final int ASCII_LETTER_A = 65;
    private static final int ASCII_LETTER_Z = 90;

    private static boolean isNum(int ascii) {
        return ascii >= ASCII_NUM_0 && ascii <= ASCII_NUM_9;
    }

    private static boolean isLetter(int ascii) {
        return ascii >= ASCII_LETTER_A && ascii <= ASCII_LETTER_Z;
    }

    public static synchronized String getNextOrgCodeV2(String code) {
        if (StringUtils.isBlank(code)) {
            return CODE_PREFIX + getStrNum(NUM_LEN, 0);
        }

        String tmpCode = code.trim();

        // ascii 0-9 ==> 48-57
        // ascii A-Z ==> 65-90 (不使用: a-z ==> 97-122)
        char[] charArr = tmpCode.toCharArray();
        int[] asciiArr = new int[charArr.length];
        for (int idx = 0, len = charArr.length; idx < len; idx++) {
            asciiArr[idx] = (int) charArr[idx];
        }

        for (int len = asciiArr.length, i = len - 1; i >= 0; i--) {
            int ascii = asciiArr[i];
            if ((i == len - 1 || i == 0) && !isNum(ascii) && !isLetter(ascii)) {
                throw new IllegalArgumentException("The format is incorrect. [code=" + code + "]");
            }

            int rs = ascii + 1;
            if (i == 0 && !isNum(rs) && !isLetter(rs)) {
                throw new IllegalArgumentException("It's already the maximum code. [code=" + code + "]");
            }

            // 未产生进位
            if ((isNum(ascii) && rs <= ASCII_NUM_9) || (isLetter(ascii) && rs <= ASCII_LETTER_Z)) {
                asciiArr[i] = rs;
                break;
            }
            // 产生进位 -> 由数字边变成字母
            if (ascii == ASCII_NUM_9 && rs == ASCII_NUM_9 + 1) {
                rs = ASCII_LETTER_A;
                asciiArr[i] = rs;
                break;
            }
            // 产生进位 -> 由字母边变成数字
            if (ascii == ASCII_LETTER_Z && rs == ASCII_LETTER_Z + 1) {
                rs = ASCII_NUM_0;
                asciiArr[i] = rs;
            }
        }

        // 转回字符串
        StringBuffer sb = new StringBuffer();
        for (int i : asciiArr) {
            char c = (char) i;
            sb.append(c);
        }

        return sb.toString();
    }

    public static synchronized String getSubOrgCodeV2(String parentCode) {
        if (StringUtils.isBlank(parentCode)) {
            throw new IllegalArgumentException("parentCode must not be blank");
        }
        String tmpCode = parentCode.trim();
        char[] charArr = tmpCode.toCharArray();
        int[] asciiArr = new int[charArr.length];
        for (int idx = 0, len = charArr.length; idx < len; idx++) {
            asciiArr[idx] = (int) charArr[idx];
        }
        int[] subAsciiArr = new int[asciiArr.length];
        for (int idx = 0, len = asciiArr.length; idx < len; idx++) {
            subAsciiArr[idx] = idx == 0 ? ASCII_LETTER_A : ASCII_NUM_0;
        }

        // 转回字符串
        StringBuffer sb = new StringBuffer(tmpCode);
        for (int i : subAsciiArr) {
            char c = (char) i;
            sb.append(c);
        }

        return sb.toString();
    }

    /**
     * 根据code 获取同级的下一个code
     *
     * @param code 指定code
     *
     * @return
     */
    public static synchronized String getNextOrgCode(String code) {
        // return getNextOrgCodeV2(code);

        if (StringUtils.isBlank(code)) {
            return CODE_PREFIX + getStrNum(NUM_LEN, 1);
        }

        int codeLength = code.length();
        String beforeCode = code.substring(0, codeLength - NUM_LEN);
        String afterCode = code.substring(codeLength - NUM_LEN);
        if (afterCode.length() != NUM_LEN) {
            throw new IllegalArgumentException("The format is incorrect. [code=" + code + "]");
        }

        int maxNum = 99;
        int num = Integer.parseInt(afterCode);
        if (num >= maxNum) {
            throw new IllegalArgumentException("It's already the maximum " + maxNum);
        }

        int nextNum = num + 1;

        return beforeCode + getStrNum(NUM_LEN, nextNum);
    }

    private static String getStrNum(int num) {
        return getStrNum(NUM_LEN, num);
    }

    private static String getStrNum(int numLen, int num) {
        return String.format("%0" + numLen + "d", num);
    }

    public static void main(String[] args) {
        String code = "B01";
        System.out.println(code);

        int max = 1000;
        for (int i = 0; i < max; i++) {
            code = getNextOrgCode(code);
            System.out.println(code);
        }
    }
}
